//
// Created by fazhehy on 2024/8/11.
//

#include "learn.h"

match_group_t lampGroup[MAX_GROUP_LEN];
uint8_t matchGroup[MAX_GROUP_LEN];
uint8_t lamp[MAX_LAMP_NUM];
uint8_t matchLen = 0;
uint8_t groupLen = 0;
uint8_t lastGroup = 0;
bool lastFirstFlag = true;

void set_lamp_seq(uint8_t group, uint8_t order, uint8_t num)
{
    lampGroup[group].sequence[order] = num;
    lampGroup[group].isMatch = true;
    if ((group+1) > groupLen)
        groupLen = group+1;
}

void lamp_seq_init()
{
    if (groupLen == 0)
        groupLen = 1;

    for (int i = 0; i < groupLen; ++i) {
        lampGroup[i].isMatch = true;
    }
}

uint8_t search_match_group(uint8_t order, uint8_t num)
{
    matchLen = 0;
    if (num != 0){
        // 记录当前灯组
        lampGroup[0].sequence[order] = num;
        // 寻找匹配组
        for (int i = 1; i < groupLen; ++i) {
            // 如果灯组处在匹配状态且当前灯号符合灯组的灯号，记录匹配组
            // 否则将灯组设置为不匹配状态
            if (lampGroup[i].sequence[order] == num && lampGroup[i].isMatch){
                matchGroup[matchLen] = i;
                matchLen ++;
            }
            else{
                lampGroup[i].isMatch = false;
            }
        }
    }
    return matchLen;
}

void add_new_sequence()
{
    if (matchLen == 0){
        lastGroup = groupLen;
        groupLen ++;
        for (int i = 0; i < MAX_SEQ_LEN; ++i) {
            lampGroup[groupLen-1].sequence[i] = lampGroup[0].sequence[i];
            lampGroup[groupLen-1].isMatch = true;
            lampGroup[0].sequence[i] = 0;
        }
    }
    else{
        if (matchLen == 1){
            lastGroup = matchGroup[0];
        }

        for (int i = 0; i < MAX_SEQ_LEN; ++i) {
            lampGroup[0].sequence[i] = 0;
        }
    }

//    for (int i = 0; i < groupLen; ++i) {
//        printf("%d-->", i);
//        for (int j = 0; j < MAX_SEQ_LEN; ++j) {
//            if (j != 0 && lampGroup[i].sequence[j] != 0)
//                printf("%d, ", lampGroup[i].sequence[j]);
//        }
//        printf("\n==========================\n");
//    }
//    printf("last group:%d\n", lastGroup);
}

uint8_t predict_lamp_num(uint8_t order)
{
    uint8_t predict_num = 0;

    // 如果没有匹配组，就回到默认位置
    if (matchLen == 0)
        return 0;

    // 灯序加一，预测下一个灯号
    order += 1;
    if (order >= MAX_SEQ_LEN)
        return 0;

    // 如果上一组优先，用来应对不改变灯组的裁判
    if (lastFirstFlag){
        // 当前匹配组是否含有上一组
        bool isExistLastGroup = false;
        for (int i = 0; i < matchLen; ++i) {
            if (matchGroup[i] == lastGroup){
                isExistLastGroup = true;
                break;
            }
        }
        // 如果有就直接返回上一次灯组的预测
        if (isExistLastGroup)
            return lampGroup[lastGroup].sequence[order];
    }

    // 如果没有，或者上一组不优先
    // 将灯号次数清零，方便统计个数
    for (int i = 0; i < MAX_LAMP_NUM; ++i) {
        lamp[i] = 0;
    }
    // 统计不同灯组的灯号出现次数
    for (int i = 0; i < matchLen; ++i) {
        lamp[lampGroup[matchGroup[i]].sequence[order]] ++;
    }

//    for (int i = 0; i < MAX_LAMP_NUM; ++i) {
//        printf("%d, ", lamp[i]);
//    }
//    printf("\n");

    // 寻找出现次数最多的灯号，并记录灯号以及最大次数
    uint8_t max_index = 0;
    uint8_t lamp_n = 0;
    for (int i = 1; i < MAX_LAMP_NUM; ++i) {
        if (lamp_n < lamp[i]){
            max_index = i;
            lamp_n = lamp[i];
        }
    }
    // 预测灯置为出现次数最多的灯号
    predict_num = max_index;
//    printf("lamp_n:%d, max_index:%d\n", lamp_n, max_index);

    // 看出现次数最多的灯号是否唯一
    uint8_t max_num = 0;
    for (int i = 0; i < MAX_LAMP_NUM; ++i) {
        if (lamp_n == lamp[i])
            max_num ++;
    }

    // 如果不唯一，就回到默认位置
    if (max_num != 1){
        predict_num = 0;
    }

    return predict_num;
}
